package com.nicole.reqresp.filters;

import com.nicole.reqresp.ReqRespProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author  xiaoying
 */
@Slf4j
public class RequestFilter implements Filter{

    private ReqRespProperties reqRespProperties;

    public RequestFilter(ReqRespProperties reqRespProperties) {
        this.reqRespProperties = reqRespProperties;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        ReqRespParamHelper reqRespParamHelper = new ReqRespParamHelper(reqRespProperties);
        HttpServletRequest httpServletRequestWrapper = httpServletRequest;
        if(checkFilter(request.getContentType())){
            httpServletRequestWrapper = new MyRequestBodyReaderWrapper(httpServletRequest);
        }
        if(reqRespProperties.isReqEnable()){
            reqRespParamHelper.requestParamLogPrint(httpServletRequestWrapper,httpServletRequest);
        }
        //包装Response，重写getOutputStream()和getWriter()方法，并用自定义的OutputStream和Writer来拦截和保存ResponseBody
        MyResponseWrapper responseWrapper = new MyResponseWrapper(httpServletResponse);
        Long dateStart = System.currentTimeMillis();
        //Spring通过DispatchServlet处理请求
        chain.doFilter(httpServletRequestWrapper, responseWrapper);
        Long dateEnd = System.currentTimeMillis();
        if(reqRespProperties.isRespEnable()){
            reqRespParamHelper.responseParamLogPrint(responseWrapper, httpServletRequest, dateStart, dateEnd);
        }
    }

    private boolean checkFilter(String contentType) {
        //是否继续拦截
        boolean filterFlag = false;
        for (String p : getContentTypes()) {
            if (StringUtils.contains(contentType, p)) {
                filterFlag = true;
                break;
            }
        }
        if (StringUtils.isEmpty(contentType)){
            filterFlag = true;
        }
        return filterFlag;
    }

    private String[] getContentTypes() {
        return new String[]{"application/json"};
    }

}
